#include "base/core/lua_parser.h"
#include "base/core/log.h"

LuaParser::LuaParser() 
{
	lua_state_ = lua_open();
	MMO_ASSERT(lua_state_);

	luaL_openlibs(lua_state_);
}

LuaParser::~LuaParser() 
{
	if (lua_state_) 
	{
		lua_close(lua_state_);
		lua_state_ = NULL;
	} 
}

bool  LuaParser::OpenFile(const char* path) 
{
	MMO_ASSERT(path);
	MMO_ASSERT(lua_state_);

	if (luaL_dofile(lua_state_, path) != 0) 
	{
		LogErrFmtPrint("load file %s fail(%s)\n", path, lua_tostring(lua_state_, -1));
		return false;
	}
	return true;
}

bool  LuaParser::OpenFileTry(const char* path) 
{
	MMO_ASSERT(path);
	MMO_ASSERT(lua_state_);

	if (luaL_dofile(lua_state_, path) != 0) 
	{
		return false;
	}
	return true;
}


bool  LuaParser::OpenString(const char* buffer) 
{
	MMO_ASSERT(buffer);
	MMO_ASSERT(lua_state_);

	if (luaL_dostring(lua_state_, buffer) != 0) 
	{
		LogErrPrint("do lua string fail");
		return false;
	}
	return true;
}


bool popTable(lua_State* L, int idx, string lastKey, string subTableKey, std::list<string> &lstSubKey)
{
	try{
		lua_pushnil(L);
		string thisKey;
		while (lua_next(L, idx) != 0){
			int keyType = lua_type(L, -2);
			if (keyType == LUA_TNUMBER)
				//lua_tonumber(L, -2);
				cout << 1;
			else if (keyType == LUA_TSTRING){
				string value = lua_tostring(L, -2);
				if (lastKey == subTableKey)
					lstSubKey.push_back(value);
				else
					thisKey = value;
			}
			else{
				cout << "Invalid key type: " << keyType << endl;
				return false;
			}
			if (lua_type(L, -1) == LUA_TTABLE)
				popTable(L, lua_gettop(L), thisKey, subTableKey, lstSubKey);
			lua_pop(L, 1);
		}
	}
	catch (const char* s){
		string errMsg = s;
		lua_pop(L, 1);
		LogErrFmtPrint("parse table keys err: %s", errMsg.c_str());
		return false;
	}
	catch (std::exception& e){
		const char* errMsg = e.what();
		lua_pop(L, 1);
		LogErrFmtPrint("parse table keys err: %s", errMsg);
		return false;
	}
	catch (...){
		const char* errMsg = lua_tostring(L, -1);
		lua_pop(L, 1);
		LogErrFmtPrint("parse table keys err: %s", errMsg);
		return false;
	}
	return true;
};


bool ParserSubTableKeys(const char* configPath, const char* mainTableNme, string subTableName, list<string>& lstSubkeys)
{
	lua_State* L = luaL_newstate();
	luaL_openlibs(L);
	luaL_dofile(L, configPath);
	lua_getglobal(L, mainTableNme);
	int type = lua_type(L, 1);
	if (type == LUA_TTABLE){
		return popTable(L, lua_gettop(L), "", subTableName, lstSubkeys);
	}
	else
		return false;
}

bool GetLuaTableValue(const LuaRef& table, const char* keyName, char* valueBuffer, unsigned valueBufferSize) 
{
    bool result = false;
    MMO_ASSERT(keyName);

    LuaRef valueRef = table[keyName];
    if (valueRef.isNil()) 
	{
        LogErrFmtPrint("load lua table value \"%s\" fail. ", keyName);
        return false;
    }

    std::string value = valueRef.cast<std::string>();
    MMOLOG_PROCESS_ERROR(valueBufferSize > value.length());

    memcpy(valueBuffer, value.c_str(), value.length() + 1);
    result = true;
Exit0:
    return result;
}